package com.android.fzmap.map;
/**
 * @author rongfzh
 * @version 1.0.0  
 */
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.location.Criteria;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.widget.Toast;

import com.android.fzmap.utils.CommonHelper;
import com.google.android.maps.GeoPoint;

/**
 * @author why
 */
public class FzLocationManager {
	private final String TAG = "FzLocationManager";
	private static Context mContext;
	private static Handler mHandler;
	private LocationManager locationManager;
	private static final int MINTIME = 2000;
	private static final int MININSTANCE = 2;
	private static FzLocationManager instance;
	private Location lastLocation = null;
	private static LocationCallBack mCallback;
	private TelephonyManager tm;
	private List<GpsSatellite> numSatelliteList = new ArrayList<GpsSatellite>(); // 卫星信号
	private int satelliteCount = 0;
	private int threadCount = 0;
	public final static int LOCATION_BASE_ID = 100;
	
	public static void init(Context c , LocationCallBack callback, Handler handler) {
		mContext = c;
		mCallback = callback;
		mHandler = handler;
	}

	private FzLocationManager() {
		tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
		locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
		locationManager.addGpsStatusListener(statusListener);
	}

	public static FzLocationManager getInstance() {
		if (null == instance) {
			instance = new FzLocationManager();
		}
		return instance;
	}

	
	private void updateToNewLocation(Location location) {
		if (location != null) {
			lastLocation = location;
			GeoPoint point;
			double latitude = location.getLatitude();
			double longitude= location.getLongitude();
			if(CommonHelper.isjustLoction){
				Map<String,Object> params = getNetWorkLocationDouble();
				point = GPSUtil.adjustLoction(latitude, longitude);
			}else{
				point = new GeoPoint(CommonHelper.getIntLatLng(latitude),CommonHelper.getIntLatLng(longitude));
			}
			
//			Toast.makeText(mContext, latitude + " " + longitude, Toast.LENGTH_SHORT).show();
			mCallback.onCurrentLocation(point);
		}
	}
	
	
	public void openGPSSettings() {
		if (locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER ) && locationManager.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER)) {
			return;
		}
		Toast.makeText(mContext, "请开启GPS和无线网络定位", Toast.LENGTH_LONG).show();
	}

	
	public void getGpsLocation() {

	// 查找到服务信息

	Criteria criteria = new Criteria();
	criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度
	criteria.setAltitudeRequired(false);
	criteria.setBearingRequired(false);
	criteria.setCostAllowed(true);
	criteria.setPowerRequirement(Criteria.POWER_LOW); // 低功耗
	String provider = locationManager.getBestProvider(criteria, true); // 获取GPS信息
		// 设置监听器，自动更新的最小时间为间隔N秒(1秒为1*1000，这样写主要为了方便)或最小位移变化超过N米
	locationManager.requestLocationUpdates(provider, MINTIME * 1000, MININSTANCE, locationListener);

	}
	
	
	/**
	 * 卫星状态监听器
	 */
	private final GpsStatus.Listener statusListener = new GpsStatus.Listener() {
		public void onGpsStatusChanged(int event) { // GPS状态变化时的回调，如卫星数
			GpsStatus status = locationManager.getGpsStatus(null); // 取当前状态
			updateGpsStatus(event, status);
		}
	};

	private void updateGpsStatus(int event, GpsStatus status) {
		if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
			int maxSatellites = status.getMaxSatellites();
			Iterator<GpsSatellite> it = status.getSatellites().iterator();
			numSatelliteList.clear();
			int count = 0;
			while (it.hasNext() && count <= maxSatellites) {
				GpsSatellite s = it.next();
				numSatelliteList.add(s);
				count++;
			}
//			Logs.d(TAG, "updateGpsStatus");
			satelliteCount = numSatelliteList.size();
//			Toast.makeText(mContext, "卫星数:" + numSatelliteList.size(), Toast.LENGTH_SHORT).show();
		}
	}
	
	private GeoPoint getNetWorkLocation(){
		tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
		GsmCellLocation gcl = (GsmCellLocation) tm.getCellLocation();
		int cid = gcl.getCid();
		int lac = gcl.getLac();

		int mcc = Integer.valueOf(tm.getNetworkOperator().substring(0,
				3));
		int mnc = Integer.valueOf(tm.getNetworkOperator().substring(3,
				5));
		try {
			// 组装JSON查询字符串
			JSONObject holder = new JSONObject();
			holder.put("version", "1.1.0");
			holder.put("host", "maps.google.com");
			// holder.put("address_language", "zh_CN");
			holder.put("request_address", true);

			JSONArray array = new JSONArray();
			JSONObject data = new JSONObject();
			data.put("cell_id", cid); // 25070
			data.put("location_area_code", lac);// 4474
			data.put("mobile_country_code", mcc);// 460
			data.put("mobile_network_code", mnc);// 0
			array.put(data);
			holder.put("cell_towers", array);

			// 创建连接，发送请求并接受回应
			DefaultHttpClient client = new DefaultHttpClient();

			HttpPost post = new HttpPost(
					"http://www.google.com/loc/json");

			StringEntity se = new StringEntity(holder.toString());

			post.setEntity(se);
			HttpResponse resp = client.execute(post);
			HttpEntity entity = resp.getEntity();
			BufferedReader br = new BufferedReader(
					new InputStreamReader(entity.getContent()));
			StringBuffer sb = new StringBuffer();
			String result = br.readLine();

			while (result != null) {
				sb.append(result);
				result = br.readLine();
			}
			JSONObject jsonObject = new JSONObject(sb.toString());

			JSONObject jsonObject1 = new JSONObject(jsonObject
					.getString("location"));

		
			GeoPoint point = new GeoPoint(CommonHelper.doubleStringToInt(jsonObject1.getString("latitude")),
					CommonHelper.doubleStringToInt(jsonObject1.getString("longitude")) );
			return point;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}
	
	private Map<String, Object> getNetWorkLocationDouble(){
		tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
		GsmCellLocation gcl = (GsmCellLocation) tm.getCellLocation();
		int cid = gcl.getCid();
		int lac = gcl.getLac();

		int mcc = Integer.valueOf(tm.getNetworkOperator().substring(0,
				3));
		int mnc = Integer.valueOf(tm.getNetworkOperator().substring(3,
				5));
		try {
			// 组装JSON查询字符串
			JSONObject holder = new JSONObject();
			holder.put("version", "1.1.0");
			holder.put("host", "maps.google.com");
			// holder.put("address_language", "zh_CN");
			holder.put("request_address", true);

			JSONArray array = new JSONArray();
			JSONObject data = new JSONObject();
			data.put("cell_id", cid); // 25070
			data.put("location_area_code", lac);// 4474
			data.put("mobile_country_code", mcc);// 460
			data.put("mobile_network_code", mnc);// 0
			array.put(data);
			holder.put("cell_towers", array);

			// 创建连接，发送请求并接受回应
			DefaultHttpClient client = new DefaultHttpClient();

			HttpPost post = new HttpPost(
					"http://www.google.com/loc/json");

			StringEntity se = new StringEntity(holder.toString());

			post.setEntity(se);
			HttpResponse resp = client.execute(post);
			HttpEntity entity = resp.getEntity();
			BufferedReader br = new BufferedReader(
					new InputStreamReader(entity.getContent()));
			StringBuffer sb = new StringBuffer();
			String result = br.readLine();

			while (result != null) {
				sb.append(result);
				result = br.readLine();
			}
			JSONObject jsonObject = new JSONObject(sb.toString());

			JSONObject jsonObject1 = new JSONObject(jsonObject
					.getString("location"));

		
			 double lat = Double.parseDouble(jsonObject1.getString("latitude"));
			 double lng = Double.parseDouble(jsonObject1.getString("longitude"));
			 
			 Map<String, Object> params = new HashMap<String, Object>();
			 params.put("latitude", lat);
			 params.put("longitude", lng);
			 
			return params;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	public void getAddress(String lat, String lag) {
		try {
			URL url = new URL("http://maps.google.cn/maps/geo?key=abcdefg&q="
					+ lat + "," + lag);
			InputStream inputStream = url.openConnection().getInputStream();
			InputStreamReader inputReader = new InputStreamReader(inputStream,
					"utf-8");
			BufferedReader bufReader = new BufferedReader(inputReader);
			String line = "", lines = "";
			while ((line = bufReader.readLine()) != null) {
				lines += line;
			}
			if (!lines.equals("")) {
	
				JSONObject jsonobject = new JSONObject(lines);
				JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark")
						.toString());
				for (int i = 0; i < jsonArray.length(); i++) {
	
	//				mTextView.setText(mTextView.getText() + "\n"
	//						+ jsonArray.getJSONObject(i).getString("address"));
				}

			}
	
		} catch (Exception e) {
			;
		}

	}
	
	
	private final LocationListener locationListener = new LocationListener() {
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

		@Override
		public void onProviderEnabled(String provider) {
		}

		@Override
		public void onProviderDisabled(String provider) {
		}

		@Override
		public void onLocationChanged(Location location) {
			Log.d(TAG, "onLocationChanged");
			updateToNewLocation(location);
		}
	};

	public GeoPoint getMyLocation() {
		GeoPoint point = null;
		//如果监听到的卫星数大于4颗，那么就使用GPS的经纬度
		if (satelliteCount > 4 ){
			if (lastLocation == null){
				if(threadCount == 1){
					
				}else{
					threadCount = 1;
					new Thread(new Runnable(){

						@Override
						public void run() {
							Message msg =  new Message();
							if(CommonHelper.isjustLoction){
								Map<String,Object> params = getNetWorkLocationDouble();
								msg.obj = GPSUtil.adjustLoction((Double)params.get("latitude"), (Double)params.get("longitude"));
								msg.what = LOCATION_BASE_ID;
							}else{
								GeoPoint point = getNetWorkLocation();
								msg.what = LOCATION_BASE_ID;
								msg.obj = point;
							}
							
							mHandler.sendMessage(msg);
							threadCount = 0;
						}
						
					}).start();
				}
			}else{
				
				if(CommonHelper.isjustLoction){
					point = GPSUtil.adjustLoction(lastLocation.getLatitude(), lastLocation.getLongitude());
				}else{
					point = new GeoPoint(
					(int) (lastLocation.getLatitude() * 1E6),
					(int) (lastLocation.getLongitude() * 1E6));
				}
				
			}
			
		}else{
			if(threadCount == 1){
				
			}else{
				threadCount = 1;
				new Thread(new Runnable(){

					@Override
					public void run() {
						Message msg =  new Message();
						if(CommonHelper.isjustLoction){
							Map<String,Object> params = getNetWorkLocationDouble();
							
//							msg.obj = GPSUtil.adjustLoction(39.9878599, 116.4509726);
							msg.obj = GPSUtil.adjustLoction((Double)params.get("latitude"), (Double)params.get("longitude"));
							msg.what = LOCATION_BASE_ID;
						}else{
							GeoPoint point = getNetWorkLocation();
							msg.what = LOCATION_BASE_ID;
							msg.obj = point;
						}
						mHandler.sendMessage(msg);
						threadCount = 0;
					}
					
				}).start();
				
			}
			
		}
		return point;
	}
	
    private static int ENOUGH_LONG = 1000 * 60;	 
	
	/** Determines whether one Location reading is better than the current Location fix 
	  * Copy from android developer site
	  * @param location  The new Location that you want to evaluate 
	  * @param currentBestLocation  The current Location fix, to which you want to compare the new one 
	  */ 
	static boolean isBetterLocation(Location location, Location currentBestLocation) { 
	    if (currentBestLocation == null) { 
	        // A new location is always better than no location 
	        return true; 
	    } 
	 
	    // Check whether the new location fix is newer or older 
	    long timeDelta = location.getTime() - currentBestLocation.getTime(); 
	    boolean isSignificantlyNewer = timeDelta > ENOUGH_LONG; 
	    boolean isSignificantlyOlder = timeDelta < -ENOUGH_LONG; 
	    boolean isNewer = timeDelta > 0; 
	 
	    // If it's been more than max interval since the current location, use the new location 
	    // because the user has likely moved 
	    if (isSignificantlyNewer) { 
	        return true; 
	    // If the new location is more than max interval older, it must be worse 
	    } else if (isSignificantlyOlder) { 
	        return false; 
	    } 
	 
	    // Check whether the new location fix is more or less accurate 
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy()); 
	    boolean isLessAccurate = accuracyDelta > 0; 
	    boolean isMoreAccurate = accuracyDelta < 0; 
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200; 
	 
	    // Check if the old and new location are from the same provider 
	    boolean isFromSameProvider = isSameProvider(location.getProvider(), 
	            currentBestLocation.getProvider()); 
	 
	    // Determine location quality using a combination of timeliness and accuracy 
	    if (isMoreAccurate) { 
	        return true; 
	    } else if (isNewer && !isLessAccurate) { 
	        return true; 
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) { 
	        return true; 
	    } 
	    return false; 
	} 
	 
	/** Checks whether two providers are the same */ 
	static boolean isSameProvider(String provider1, String provider2) { 
	    if (provider1 == null) { 
	      return provider2 == null; 
	    } 
	    return provider1.equals(provider2); 
	}
	
	public interface LocationCallBack{
		/**
		 * 当前位置
		 * @param location 
		 */
		void onCurrentLocation(GeoPoint location);
	}
	
	public void destoryLocationManager(){
		Log.d(TAG, "destoryLocationManager");
		locationManager.removeUpdates(locationListener);
	}
	
	/***wifi定位*********************************
	private void requestTelLocation() {

		TelephonyManager mTelMan = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		String operator = mTelMan.getNetworkOperator();
		String mcc = operator.substring(0, 3);
		String mnc = operator.substring(3);

		GsmCellLocation location = (GsmCellLocation) mTelMan.getCellLocation();
		int cid = location.getCid();
		int lac = location.getLac();

		JSONObject tower = new JSONObject();
		try {
		tower.put("cell_id", cid);
		tower.put("location_area_code", lac);
		tower.put("mobile_country_code", mcc);
		tower.put("mobile_network_code", mnc);
		} catch (JSONException e) {
		Log.e(TAG, "call JSONObject's put failed", e);
		}

		JSONArray array = new JSONArray();
		array.put(tower);

		List<NeighboringCellInfo> list = mTelMan.getNeighboringCellInfo();
		Iterator<NeighboringCellInfo> iter = list.iterator();
		NeighboringCellInfo cellInfo;
		JSONObject tempTower;


		while (iter.hasNext()) {
		cellInfo = iter.next();
		tempTower = new JSONObject();
		try {
		tempTower.put("cell_id", cellInfo.getCid());
		tempTower.put("location_area_code", cellInfo.getLac());
		tempTower.put("mobile_country_code", mcc);
		tempTower.put("mobile_network_code", mnc);
		} catch (JSONException e) {
		Log.e(TAG, "call JSONObject's put failed", e);
		}
		array.put(tempTower);
		}

		JSONObject object = createJSONObject("cell_towers", array);
		requestLocation(object);
		}

		private void requestWIFILocation() {
		WifiManager wifiMan = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		WifiInfo info = wifiMan.getConnectionInfo();
		String mac = info.getMacAddress();
		String ssid = info.getSSID();

		JSONObject wifi = new JSONObject();
		try {
		wifi.put("mac_address", mac);
		wifi.put("ssid", ssid);
		} catch (JSONException e) {
		e.printStackTrace();
		}

		JSONArray array = new JSONArray();
		array.put(wifi);

		JSONObject object = createJSONObject("wifi_towers", array);
		requestLocation(object);
		}

		private void requestLocation(JSONObject object) {


		Logs.d(TAG, "requestLocation: " + object.toString());
		HttpClient client = new DefaultHttpClient();
		HttpPost post = new HttpPost("http://www.google.com/loc/json");
		try {
		StringEntity entity = new StringEntity(object.toString());
		post.setEntity(entity);
		} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
		}

		try {
		HttpResponse resp = client.execute(post);
		HttpEntity entity = resp.getEntity();
		BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
		StringBuffer buffer = new StringBuffer();
		String result = br.readLine();
		while (result != null) {
		buffer.append(result);
		result = br.readLine();
		}

		Logs.d(TAG, buffer.toString());
		} catch (ClientProtocolException e) {
		e.printStackTrace();
		} catch (IOException e) {
		e.printStackTrace();
		}
		}
		private JSONObject createJSONObject(String arrayName, JSONArray array) {


			JSONObject object = new JSONObject();
			try {
			object.put("version", "1.1.0");
			object.put("host", "maps.google.com");
			object.put(arrayName, array);
			} catch (JSONException e) {
			Log.e(TAG, "call JSONObject's put failed", e);
			}
			return object;
			}
		*************************/

}
